#include "console_listener.hpp"
#include <iostream>
#include <poll.h>   // For poll()
#include <unistd.h> // For STDIN_FILENO

ConsoleListener::ConsoleListener() : is_running_(false) {}

ConsoleListener::~ConsoleListener() {
    stop();
}

void ConsoleListener::start() {
    if (is_running_) {
        return;
    }
    is_running_ = true;
    listener_thread_ = std::thread(&ConsoleListener::listenerLoop, this);
}

void ConsoleListener::stop() {
    if (!is_running_.exchange(false)) {
        return; // 已经停止
    }
    if (listener_thread_.joinable()) {
        // 非阻塞的 listenerLoop 会在 is_running_ 变为 false 后自动退出，
        // 所以 join() 会很快返回。
        listener_thread_.join();
    }
}

void ConsoleListener::listenerLoop() {
    struct pollfd fds[1];
    fds[0].fd = STDIN_FILENO; // 监听标准输入文件描述符
    fds[0].events = POLLIN;  // 关心有数据可读的事件

    std::cout << "控制台监听已启动。输入 'p' 拍照, 'q' 或 'exit' 退出。" << std::endl;
    std::cout << "> " << std::flush;

    while (is_running_) {
        // 等待100毫秒，检查是否有输入
        int ret = poll(fds, 1, 100); 

        if (ret > 0) {
            // 有数据可读
            if (fds[0].revents & POLLIN) {
                std::string line;
                if (std::getline(std::cin, line)) {
                    if (!line.empty()) {
                        std::lock_guard<std::mutex> lock(queue_mutex_);
                        command_queue_.push(line);
                    }
                    if(is_running_) { // 如果还在运行，打印下一个提示符
                       std::cout << "> " << std::flush;
                    }
                } else {
                    // 输入流关闭 (例如 Ctrl+D)
                    is_running_ = false;
                }
            }
        } else if (ret < 0) {
            // poll 发生错误
            is_running_ = false;
        }
        // 如果 ret == 0 (超时)，则什么都不做，直接进入下一次循环
        // 这使得循环能持续检查 is_running_ 标志
    }
    std::cout << "控制台监听线程已停止。" << std::endl;
}

std::optional<std::string> ConsoleListener::getCommand() {
    std::lock_guard<std::mutex> lock(queue_mutex_);
    if (command_queue_.empty()) {
        return std::nullopt;
    }
    std::string cmd = command_queue_.front();
    command_queue_.pop();
    return cmd;
}